﻿using AutoMapper;
using Lanbt.Core.Cache;
using Lanbt.Core.Entity.Dto;
using Lanbt.Core.Entity.Dto.lanbt_user;
using Lanbt.Core.Entity.EntityDB;
using Lanbt.Core.Repository.SqlService.IRepository;
using Lanbt.Core.Service.SqlService.IService;
using Lanbt.Core.Utility;
using Lanbt.Core.Utility.ExceptionExtent;
using Lanbt.Core.Utility.Extent;
using Lanbt.Core.Utility.Helper;
using System.Security.Claims;

namespace Lanbt.Core.Service.SqlService
{
    public class UserService : IUserService
    {
        private readonly IUserRepository _userRepository;
        private readonly IRoleRepository _roleRepository;
        private readonly IPowerRepository _powerRepository;
        private readonly IMapper _mapper;

        public UserService(IUserRepository userRepository, IRoleRepository roleRepository, IMapper mapper,
            IPowerRepository powerRepository)
        {
            _userRepository = userRepository;
            _roleRepository = roleRepository;
            _mapper = mapper;
            _powerRepository = powerRepository;
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public async Task<ResultOutput<string>> Input(LoginInput input)
        {
            var user = await _userRepository.FirstOrDefault(x => x.UserName == input.UserName);
            if (user.IsNull())
            {
                throw new Exception("用户不存在");
            }

            string pwd = EncryptHelper.MD5Encrypt(input.Password);
            if (!pwd.Equals(user.Password))
            {
                throw new Exception("密码错误，请重新输入");
            }

            var authTime = DateTime.Now;
            var expiresAt = authTime.AddHours(10);//到期时间
            var claims = new[]
            {
                new Claim("UserName", user.UserName),
                new Claim("Name", user.Name),
                new Claim("Id", user.ID),
            };

            var token = JwtHelper.CreateToken(claims,authTime,expiresAt);

            if (token.IsNotNullOrEmpty())
            {
                await GetUserById(user.ID);
            }

            return new ResultOutput<string>(token.ToString());
        }

        /// <summary>
        /// 根据用户id获取用户
        /// </summary>
        /// <param name="id">用户ID</param>
        /// <returns></returns>
        public async Task<ResultOutput<GetCurrentUserOutput>> GetUserById(string id)
        {
            var res = new ResultOutput<GetCurrentUserOutput>();
            if (id.IsNullOrEmpty())
            {
                return res.AddError("请先登录！");
            }

            var user = await _userRepository.FirstOrDefault(q => q.ID == id);
            if (user == null)
            {
                return res.AddError("用户不存在，请联系管理员");
            }

            var currentUser = _mapper.Map<GetCurrentUserOutput>(user);
            if (currentUser.IsAdmin)
                currentUser.RoleNames.Add("超级管理员");
            else
            {
                //角色名称集合
                if (user.RoleIds.IsNotNullOrEmpty())
                {
                    //角色Ids
                    var roleIds = user.RoleIds.Split(',').ToList();
                    var lanbtRoles = await _roleRepository.Query(q => roleIds.Contains(q.ID));
                    if (lanbtRoles.Count > 0)
                    {
                        currentUser.RoleNames = lanbtRoles.Select(q => q.Name).ToList();
                        currentUser.RoleIds = lanbtRoles.Select(q => q.ID).ToList();
                    }
                    
                    foreach (var lanbtRole in lanbtRoles)
                    {
                        if (lanbtRole.PowerIds.IsNotNullOrEmpty())
                        {
                            var powerSorts = lanbtRole.PowerIds.LanbtSplit(',').ToList();
                            var lanbtPowers = await _powerRepository.Query(q => powerSorts.Contains(q.Sort.ToString()) && q.IsEnable && q.MenuCode!= null);
                            foreach (var lanbtPower in lanbtPowers)
                            {
                                lanbtPower.MenuCode = lanbtPower.MenuCode.Replace(';', ',').Replace('：', ':');
                                string[] powerArr = lanbtPower.MenuCode.LanbtSplit(',');
                                if (powerArr.Length > 0)
                                {
                                    foreach (var item in powerArr)
                                    {
                                        if (!currentUser.PowerList.Any(q => q == item))
                                        {
                                            currentUser.PowerList.Add(item);
                                        }
                                    }
                                }
                                else
                                {
                                    if (!currentUser.PowerList.Any(q => q == lanbtPower.MenuCode))
                                    {
                                        currentUser.PowerList.Add(lanbtPower.MenuCode);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            //缓存
            CacheFactory.Cache.SetCache(string.Format(CacheKeys.login_userid, user.ID), currentUser, DateTime.Now.AddHours(8));

            return res.ResultInput(currentUser);
        }

        public async Task<ResultOutput<GetUserInfo>> GetUserInfo(string userId)
        {
            var user = await _userRepository.FirstOrDefault(q => q.ID == userId);
            if (user == null)
            {
                throw new LanbtException(ExceptionModel.EXCEPTION, "用户不存在");
            }
            user.Password = "******";
            user.HeadUrl = user.HeadUrl ?? "https://tva1.sinaimg.cn/crop.0.0.118.118.180/5db11ff4gw1e77d3nqrv8j203b03cweg.jpg";
            var result = new ResultOutput<GetUserInfo>();
            result.Result = _mapper.Map<GetUserInfo>(user);
            return result;
        }

        /// <summary>
        /// 获取分页用户列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PagesResultOutput<QueryUsersOutput>> QueryPagesUsers(QueryUsersInput input)
        {
            var where = Extensions.Load<lanbt_user>();
            if (input.Name.IsNotNull())
            {
                where = where.And(q => q.Name.ToLower().Contains(input.Name.ToTrimAndLower()) || q.UserName.ToLower().Contains(input.Name.ToTrimAndLower()));
            }

            var result =
                await _userRepository.QueryToPageListOrderBy(input.PageIndex, input.PageSize, where, q =>new { q.CreateTime });

            var usersOutput = _mapper.Map<List<QueryUsersOutput>>(result.Item2);

            foreach (var user in usersOutput)
            {
                if (user.RoleIdList.Count > 0)
                {
                    var roles = await _roleRepository.Query(q => user.RoleIdList.Contains(q.ID));
                    if (roles.Count > 0)
                    {
                        var roleNames = roles.Select(q => q.Name);
                        user.RoleNames = string.Join(",", roleNames);
                    }
                }
            }

            return new PagesResultOutput<QueryUsersOutput>(result.Item1, usersOutput);
        }

        /// <summary>
        /// 添加单个用户
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ResultOutput<string>> InsertUser(InsertUserInput input)
        {
            var result = new ResultOutput<string>();

            if (input.UserName.ToLower().Equals("admin") || input.UserName.ToLower().Equals("administrator"))
            {
                result.ErrorMsg = "登录名不允许使用管理名称";
                return result;
            }

            if (!input.Password.Equals(input.ConfirmPwd))
            {
                result.ErrorMsg = "两次密码不一致";
                return result;
            }

            var count = _userRepository.Query(q => q.UserName.Equals(input.UserName)).Result.Count;
            if (count > 0)
            {
                result.ErrorMsg = "登录名重复了，再想一个吧";
                return result;
            }

            lanbt_user user = _mapper.Map<lanbt_user>(input);

            var id = await _userRepository.InsertOne(user);
            if (id.IsNull())
            {
                result.ErrorMsg = "添加失败";
                return result;
            }

            return new ResultOutput<string>(id);
        }

        /// <summary>
        /// 添加超级管理员
        /// </summary>
        /// <returns></returns>
        public async Task<ResultOutput<bool>> AddAdmin()
        {
            var user = await _userRepository.FirstOrDefault(q => q.UserName.Equals("admin"));
            if (user.IsNotNull())
            {
                return new ResultOutput<bool>().AddError("超级管理员只能有一个");
            }
            lanbt_user admin = new lanbt_user
            {
                Name = "超级管理员",
                UserName = "admin",
                Password = "123456",
                IsAdmin = true,
            };
            admin.Password = EncryptHelper.MD5Encrypt(admin.Password);
            await _userRepository.InsertOne(admin);
            return new ResultOutput<bool>(true);
        }

        /// <summary>
        /// 根据id删除单个用户
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public async Task DeleteById(string id)
        {
            var user = await _userRepository.FirstOrDefault(q => q.ID == id);
            if (user == null)
            {
                throw new Exception("用户不存在");
            }

            if (user.IsAdmin)
            {
                throw new Exception("无法删除超级管理员");
            }

            await _userRepository.Delete_false(id);
        }

        /// <summary>
        /// 根据id批量删除用户
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public async Task DeleteByIds(List<string> ids)
        {
            var users = await _userRepository.Query(q => ids.Contains(q.ID));
            if (users.Count == 0)
            {
                throw new Exception("用户不存在");
            }

            var adminCount = users.Where(u => u.IsAdmin).Count();
            if (adminCount > 0)
            {
                throw new Exception("无法删除超级管理员");
            }

            await _userRepository.Delete_false(ids);
        }

        /// <summary>
        /// 修改用户信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task Update(UpdateUserInput input)
        {
            var user = await _userRepository.FirstOrDefault(q => q.ID.Equals(input.ID));
            if (user.IsNull())
            {
                throw new LanbtException(ExceptionModel.ENTITY_EXISTEN,"用户不存在");
            }
            if (user.Name.IsNullOrWhiteSpace())
            {
                throw new LanbtException(ExceptionModel.PARAMS_ERROR, "名称不能为空");
            }
            user.HeadUrl = input.HeadUrl.IsNullOrWhiteSpace() ? input.HeadUrl : "https://tva1.sinaimg.cn/crop.0.0.118.118.180/5db11ff4gw1e77d3nqrv8j203b03cweg.jpg";
            user.Name = input.Name;
            user.Mobile = input.Mobile;
            user.Email = input.Email;

            

            await _userRepository.UpdateOne(user);
        }

        /// <summary>
        /// 根据id修改是否是管理员
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<ResultOutput<string>> UpdateIsAdminById(string id)
        {
            var res = new ResultOutput<string>();
            var user = await _userRepository.FirstOrDefault(q => q.ID.Equals(id));

            if (user.IsNull())
            {
                return res.AddError("用户不存在，请刷新重试");
            }

            if (user.UserName.Equals("admin"))
            {
                return res.AddError("系统用户不能降为普通用户");
            }

            user.IsAdmin = !user.IsAdmin;
            await _userRepository.UpdateOne(user);
            return res.ResultInput("设置成功");
        }

        /// <summary>
        /// 修改用户密码
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="LanbtException"></exception>
        public async Task<ResultOutput> UpdatePassword(UpdatePasswordInput input)
        {
            var user = await _userRepository.FirstOrDefault(q => q.ID == input.Id);
            if (user.IsNull())
            {
                throw new LanbtException(ExceptionModel.ENTITY_EXISTEN, "用户不存在");
            }
            if(EncryptHelper.MD5Encrypt(input.OldPassword) != user.Password)
            {
                throw new LanbtException(ExceptionModel.WARING, "密码错误");
            }
            if(input.Password.Length < 6 || input.Password.Length > 12 || input.Password.Contains(" "))
            {
                throw new LanbtException(ExceptionModel.WARING, "密码必须6到18位，且不能出现空格");
            }
            if(input.Password != input.ConfirmPassword)
            {
                throw new LanbtException(ExceptionModel.WARING, "两次密码不一致");
            }
            var password = EncryptHelper.MD5Encrypt(input.Password);
            user.Password = password; 
            await _userRepository.UpdateOne(user);
            return new ResultOutput("修改成功");
        }

        /// <summary>
        /// 修改角色ids
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<ResultOutput<string>> UpdateRoleIdsById(UpdateRoleIdsByIdInput input)
        {
            var res = new ResultOutput<string>();
            var user = await _userRepository.FirstOrDefault(q => q.ID.Equals(input.Id));
            if (user.IsNull())
            {
                return res.AddError("用户不存在，请刷新重试");
            }

            user.RoleIds = string.Join(",", input.RoleIds);

            await _userRepository.UpdateOne(user);
            return res.ResultInput("分配成功");
        }
    }
}